<!--
  trees 递归显示组件
  github：https://github.com/jin-yufeng/Parser 
  docs：https://jin-yufeng.github.io/Parser
  插件市场：https://ext.dcloud.net.cn/plugin?id=805
  author：JinYufeng
  update：2020/04/13
-->
<template>
  <view class="interlayer">
    <block v-for="(n, index) in nodes" v-bind:key="index">
      <!--图片-->
      <!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
      <rich-text v-if="n.name=='img'" :id="n.attrs.id" class="_img" :style="''+handler.getStyle(n.attrs.style)"
                 :nodes="handler.getNode(n,!lazyLoad||imgLoad)"
                 :data-attrs="n.attrs" @tap="imgtap" @longpress="imglongtap"/>
      <!--#endif-->
      <!--#ifdef MP-BAIDU || MP-TOUTIAO-->
      <rich-text v-if="n.name=='img'" :id="n.attrs.id" class="_img" :style="n.attrs.contain" :nodes='[n]'
                 :data-attrs="n.attrs"
                 @tap="imgtap" @longpress="imglongtap"/>
      <!--#endif-->
      <!--文本-->
      <!--#ifdef MP-WEIXIN || MP-QQ || APP-PLUS-->
      <rich-text v-else-if="n.decode" class="_entity" :nodes="[n]"></rich-text>
      <!--#endif-->
      <text v-else-if="n.type=='text'" decode>{{ n.text }}</text>
      <text v-else-if="n.name=='br'">\n</text>
      <!--视频-->
      <view v-else-if="n.name=='video'">
        <view v-if="(!loadVideo||n.lazyLoad)&&!(controls[n.attrs.id]&&controls[n.attrs.id].play)" :id="n.attrs.id"
              :class="'_video '+(n.attrs.class||'')"
              :style="n.attrs.style" @tap="_loadVideo"/>
        <video v-else :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style"
               :autoplay="n.attrs.autoplay||(controls[n.attrs.id]&&controls[n.attrs.id].play)"
               :controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :poster="n.attrs.poster"
               :src="n.attrs.source[(controls[n.attrs.id]&&controls[n.attrs.id].index)||0]"
               :unit-id="n.attrs['unit-id']" :data-id="n.attrs.id" data-from="video" data-source="source" @error="error"
               @play="play"/>
      </view>
      <!--音频-->
      <audio v-else-if="n.name=='audio'" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author"
             :autoplay="n.attrs.autoplay"
             :controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster"
             :src="n.attrs.source[(controls[n.attrs.id]&&controls[n.attrs.id].index)||0]"
             :data-id="n.attrs.id" data-from="audio" data-source="source" @error="error" @play="play"/>
      <!--链接-->
      <view v-else-if="n.name=='a'" :class="'_a '+(n.attrs.class||'')" hover-class="_hover" :style="n.attrs.style"
            :data-attrs="n.attrs" @tap="linkpress">
        <trees class="_span" :nodes="n.children"/>
      </view>
      <!--广告（按需打开注释）-->
      <!--#ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO-->
      <!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :unit-id="n.attrs['unit-id']"
       data-from="ad" @error="error" />-->
      <!--#endif-->
      <!--#ifdef MP-BAIDU-->
      <!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :appid="n.attrs.appid"
       :apid="n.attrs.apid" :type="n.attrs.type" data-from="ad" @error="error" />-->
      <!--#endif-->
      <!--#ifdef APP-PLUS-->
      <!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :adpid="n.attrs.adpid"
       data-from="ad" @error="error" />-->
      <!--#endif-->
      <!--列表-->
      <view v-else-if="n.name=='li'" :id="n.attrs.id" :class="n.attrs.class"
            :style="(n.attrs.style||'')+';display:flex'">
        <view v-if="n.type=='ol'" class="_ol-bef">{{ n.num }}</view>
        <view v-else class="_ul-bef">
          <view v-if="n.floor%3==0" class="_ul-p1">█</view>
          <view v-else-if="n.floor%3==2" class="_ul-p2"/>
          <view v-else class="_ul-p1" style="border-radius:50%">█</view>
        </view>
        <!--#ifdef MP-ALIPAY-->
        <view class="_li">
          <trees :nodes="n.children"/>
        </view>
        <!--#endif-->
        <!--#ifndef MP-ALIPAY-->
        <trees class="_li" :nodes="n.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo"/>
        <!--#endif-->
      </view>
      <!--表格-->
      <view v-else-if="n.name=='table'&&n.c" :id="n.attrs.id" :class="n.attrs.class"
            :style="(n.attrs.style||'')+';display:table'">
        <view v-for="(tbody, i) in n.children" v-bind:key="i" :class="tbody.attrs.class"
              :style="(tbody.attrs.style||'')+(tbody.name[0]=='t'?';display:table-'+(tbody.name=='tr'?'row':'row-group'):'')">
          <view v-for="(tr, j) in tbody.children" v-bind:key="j" :class="tr.attrs.class"
                :style="(tr.attrs.style||'')+(tr.name[0]=='t'?';display:table-'+(tr.name=='tr'?'row':'cell'):'')">
            <trees v-if="tr.name=='td'" :nodes="tr.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo"/>
            <block v-else>
              <!--#ifdef MP-ALIPAY-->
              <view v-for="(td, k) in tr.children" v-bind:key="k" :class="td.attrs.class"
                    :style="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')">
                <trees :nodes="td.children"/>
              </view>
              <!--#endif-->
              <!--#ifndef MP-ALIPAY-->
              <trees v-for="(td, k) in tr.children" v-bind:key="k" :class="td.attrs.class"
                     :style="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')"
                     :nodes="td.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo"/>
              <!--#endif-->
            </block>
          </view>
        </view>
      </view>
      <!--#ifdef APP-PLUS-->
      <iframe v-else-if="n.name=='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen"
              :frameborder="n.attrs.frameborder"
              :width="n.attrs.width" :height="n.attrs.height" :src="n.attrs.src"/>
      <embed v-else-if="n.name=='embed'" :style="n.attrs.style" :width="n.attrs.width" :height="n.attrs.height"
             :src="n.attrs.src"/>
      <!--#endif-->
      <!--富文本-->
      <!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
      <rich-text v-else-if="handler.useRichText(n)" :id="n.attrs.id" :class="'_p __'+n.name" :nodes="[n]"/>
      <!--#endif-->
      <!--#ifdef MP-BAIDU || MP-TOUTIAO-->
      <rich-text v-else-if="!(n.c||n.continue)" :id="n.attrs.id" :class="_p" :style="n.attrs.contain" :nodes="[n]"/>
      <!--#endif-->
      <!--#ifdef MP-ALIPAY-->
      <view v-else :id="n.attrs.id" :class="'_'+n.name+' '+(n.attrs.class||'')" :style="n.attrs.style">
        <trees :nodes="n.children"/>
      </view>
      <!--#endif-->
      <!--#ifndef MP-ALIPAY-->
      <trees v-else :class="(n.attrs.id||'')+' _'+n.name+' '+(n.attrs.class||'')" :style="n.attrs.style"
             :nodes="n.children"
             :lazyLoad="lazyLoad" :loadVideo="loadVideo"/>
      <!--#endif-->
    </block>
  </view>
</template>
<script module="handler" lang="wxs" src="./handler.wxs"></script>
<script module="handler" lang="sjs" src="./handler.sjs"></script>
<script>
global.Parser = {};
import trees from './trees'

export default {
  components: {
    trees
  },
  name: 'trees',
  data() {
    return {
      controls: {},
      // #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
      imgLoad: false,
      // #endif
      // #ifndef APP-PLUS
      loadVideo: true
      // #endif
    }
  },
  props: {
    nodes: Array,
    // #ifdef MP-WEIXIN || MP-QQ || H5 || APP-PLUS
    lazyLoad: Boolean,
    // #endif
    // #ifdef APP-PLUS
    loadVideo: Boolean
    // #endif
  },
  mounted() {
    // 获取顶层组件
    this.top = this.$parent;
    while (this.top.$options.name != 'parser') {
      if (this.top.top) {
        this.top = this.top.top;
        break;
      }
      this.top = this.top.$parent;
    }
  },
  // #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
  beforeDestroy() {
    if (this.observer)
      this.observer.disconnect();
  },
  // #endif
  methods: {
    // #ifndef MP-ALIPAY
    play(e) {
      if (this.top.videoContexts.length > 1 && this.top.autopause)
        for (var i = this.top.videoContexts.length; i--;)
          if (this.top.videoContexts[i].id != e.currentTarget.dataset.id)
            this.top.videoContexts[i].pause();
    },
    // #endif
    imgtap(e) {
      var attrs = e.currentTarget.dataset.attrs;
      if (!attrs.ignore) {
        var preview = true, data = {
          id: e.target.id,
          src: attrs.src,
          ignore: () => preview = false
        };
        global.Parser.onImgtap && global.Parser.onImgtap(data);
        this.top.$emit('imgtap', data);
        if (preview) {
          var urls = this.top.imgList,
              current = urls[attrs.i] ? parseInt(attrs.i) : (urls = [attrs.src], 0);
          uni.previewImage({
            current,
            urls
          })
        }
      }
    },
    imglongtap(e) {
      var attrs = e.item.dataset.attrs;
      if (!attrs.ignore)
        this.top.$emit('imglongtap', {
          id: e.target.id,
          src: attrs.src
        })
    },
    linkpress(e) {
      var jump = true,
          attrs = e.currentTarget.dataset.attrs;
      attrs.ignore = () => jump = false;
      global.Parser.onLinkpress && global.Parser.onLinkpress(attrs);
      this.top.$emit('linkpress', attrs);
      if (jump) {
        // #ifdef MP
        if (attrs['app-id']) {
          return uni.navigateToMiniProgram({
            appId: attrs['app-id'],
            path: attrs.path
          })
        }
        // #endif
        if (attrs.href) {
          if (attrs.href[0] == '#') {
            if (this.top.useAnchor)
              this.top.navigateTo({
                id: attrs.href.substring(1)
              })
          } else if (attrs.href.indexOf('http') == 0 || attrs.href.indexOf('//') == 0) {
            // #ifdef APP-PLUS
            plus.runtime.openWeb(attrs.href);
            // #endif
            // #ifndef APP-PLUS
            uni.setClipboardData({
              data: attrs.href,
              success: () =>
                  uni.showToast({
                    title: '链接已复制'
                  })
            })
            // #endif
          } else
            uni.navigateTo({
              url: attrs.href
            })
        }
      }
    },
    error(e) {
      var context, target = e.currentTarget,
          source = target.dataset.from;
      if (source == 'video' || source == 'audio') {
        // 加载其他 source
        var index = this.controls[target.id] ? this.controls[target.id].index + 1 : 1;
        if (index < target.dataset.source.length)
          this.$set(this.controls, target.id + '.index', index);
        if (source == 'video') context = uni.createVideoContext(target.id, this);
      }
      this.top && this.top.$emit('error', {
        source,
        target,
        errMsg: e.detail.errMsg,
        errCode: e.detail.errCode,
        context
      });
    },
    _loadVideo(e) {
      this.$set(this.controls, e.currentTarget.id, {
        play: true,
        index: 0
      })
    }
  }
}
</script>

<style>
/* 在这里引入自定义样式 */

/* 链接和图片效果 */
._a {
  display: inline;
  color: #366092;
  word-break: break-all;
  padding: 1.5px 0 1.5px 0;
}

._hover {
  opacity: 0.7;
  text-decoration: underline;
}

._img {
  display: inline-block;
  text-indent: 0;
}

/* #ifdef MP-WEIXIN */
:host {
  display: inline;
}

/* #endif */

/* #ifdef MP */
.interlayer {
  align-content: inherit;
  align-items: inherit;
  display: inherit;
  flex-direction: inherit;
  flex-wrap: inherit;
  justify-content: inherit;
  width: 100%;
  white-space: inherit;
}

/* #endif */

._b,
._strong {
  font-weight: bold;
}

._blockquote,
._div,
._p,
._ol,
._ul,
._li {
  display: block;
}

._code {
  font-family: monospace;
}

._del {
  text-decoration: line-through;
}

._em,
._i {
  font-style: italic;
}

._h1 {
  font-size: 2em;
}

._h2 {
  font-size: 1.5em;
}

._h3 {
  font-size: 1.17em;
}

._h5 {
  font-size: 0.83em;
}

._h6 {
  font-size: 0.67em;
}

._h1,
._h2,
._h3,
._h4,
._h5,
._h6 {
  display: block;
  font-weight: bold;
}

._ins {
  text-decoration: underline;
}

._li {
  flex: 1;
  width: 0;
}

._ol-bef {
  margin-right: 5px;
  text-align: right;
  width: 36px;
}

._ul-bef {
  line-height: normal;
  margin: 0 12px 0 23px;
}

._ol-bef,
._ul_bef {
  flex: none;
  user-select: none;
}

._ul-p1 {
  display: inline-block;
  height: 0.3em;
  line-height: 0.3em;
  overflow: hidden;
  width: 0.3em;
}

._ul-p2 {
  border: 0.05em solid black;
  border-radius: 50%;
  display: inline-block;
  height: 0.23em;
  width: 0.23em;
}

._q::before {
  content: '"';
}

._q::after {
  content: '"';
}

._sub {
  font-size: smaller;
  vertical-align: sub;
}

._sup {
  font-size: smaller;
  vertical-align: super;
}

/* #ifndef MP-WEIXIN */
._abbr,
._b,
._code,
._del,
._em,
._i,
._ins,
._label,
._q,
._span,
._strong,
._sub,
._sup {
  display: inline;
}

/* #endif */

/* #ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY */
.__bdo,
.__bdi,
.__ruby,
.__rt,
._entity {
  display: inline-block;
}

/* #endif */
._video {
  background-color: black;
  display: inline-block;
  height: 225px;
  position: relative;
  width: 300px;
}

._video::after {
  border-color: transparent transparent transparent white;
  border-style: solid;
  border-width: 15px 0 15px 30px;
  content: '';
  left: 50%;
  margin: -15px 0 0 -15px;
  position: absolute;
  top: 50%;
}
</style>
